package com.laze.mywanandroid.base

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.gson.JsonParseException
import com.hjq.toast.ToastUtils
import com.laze.mywanandroid.R
import com.laze.mywanandroid.api.ApiException
import com.laze.mywanandroid.app.App
import com.orhanobut.logger.Logger
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.util.concurrent.CancellationException

typealias Block<T> = suspend () -> T
typealias Error = suspend (e: Exception) -> Unit
typealias Cancel = suspend (e: Exception) -> Unit

open class BaseViewModel : ViewModel() {

    fun toast(msg: String) {
        ToastUtils.show(msg)
    }

    fun loge(msg: String) {
        Logger.d(msg)
    }


    /**
     * 创建并执行协程
     * @param block 协程中执行
     * @param error 错误时执行
     * @return Job
     */
    fun launch(block: Block<Unit>, error: Error? = null, cancel: Cancel? = null): Job {
        return viewModelScope.launch {
            try {
                block.invoke()
            } catch (e: Exception) {
                when (e) {
                    is CancellationException -> cancel?.invoke(e)
                    else -> {
                        onError(e)
                        error?.invoke(e)
                    }
                }
            }
        }
    }

    fun <T> async(block: Block<T>) = viewModelScope.async { block.invoke() }

    /**
     * 统一处理错误
     * @param e 异常
     */
    private fun onError(e: Exception) {
        when (e) {
            is ApiException -> {
                when (e.code) {
                    -1001 -> {
                        //Todo 登录失败
                    }
                    else -> loge(e.message)
                }
            }
            is ConnectException -> toast(App.instance.getString(R.string.network_connection_failed))
            is SocketTimeoutException -> toast(App.instance.getString(R.string.network_request_timeout))
            is JsonParseException -> toast(App.instance.getString(R.string.api_data_parse_error))
            else -> e.message?.let { loge(it) }
        }
    }
}